package com.bw;
import com.alibaba.alink.operator.batch.BatchOperator;
import com.alibaba.alink.operator.batch.dataproc.SplitBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalRegressionBatchOp;
import com.alibaba.alink.operator.batch.regression.*;
import com.alibaba.alink.operator.batch.sink.CsvSinkBatchOp;
import com.alibaba.alink.operator.batch.source.CsvSourceBatchOp;
import com.alibaba.alink.operator.common.evaluation.RegressionMetrics;

public class Month06 {
    public static void main(String[] args) throws Exception {
        // TODO: 2025/7/4 1.读数据
        String filePath = "data/boston_housing.csv";
        String schema
                = "x1 double," +
                " x2 double," +
                " x3 double," +
                " x4 double," +
                " x5 double," +
                " x6 double," +
                " x7 double," +
                " x8 double," +
                " x9 double," +
                " x10 double," +
                " x11 double," +
                " x12 double," +
                " x13 double," +
                " y double";
        CsvSourceBatchOp csvSource = new CsvSourceBatchOp()
                .setFilePath(filePath)
                .setSchemaStr(schema)
                .setIgnoreFirstLine(true)
                .setFieldDelimiter(",");
        csvSource.print(3);
        // TODO: 2025/7/4 2.特征工程 对特征列的数据 进行加工处理 以便于算法的处理
        // TODO: 2025/7/4 3.拆分数据 训练数据集->算法模型训练  测试数据集->用于测试算法模型
        // setFraction 拆分到左端的数据集比例
        BatchOperator<?> spliter = new SplitBatchOp().setFraction(0.8);
        // 拆分出来的数据集 拆分器连接总的数据集 获取0.8的数据  训练集
        BatchOperator<?> trainDate = spliter.linkFrom(csvSource);
        //  获取测流数据为 测试集
        BatchOperator<?> testDate = spliter.getSideOutput(0);

        // TODO: 2025/7/4 将训练集和测试集的总条目数打印出来
        System.out.println(trainDate.count());
        System.out.println(testDate.count());
        // TODO: 2025/7/4 7.调优处理(将算法的参数进行调整之后 重复4/5/6的三个步骤 )对比获取最优模型
//        extracted(trainDate, testDate,0.1,100);//最优
//        extracted(trainDate, testDate,0.01,200);
//        extracted(trainDate, testDate,0.1,200);
//        extracted(trainDate, testDate,0.01,500);
//        extracted(trainDate, testDate,0.001,1000);


        testRidge(trainDate, testDate,0.1,0.1,100);//最优
        testRidge(trainDate, testDate,0.001,0.01,200);
        testRidge(trainDate, testDate,0.01,0.1,200);
        testRidge(trainDate, testDate,0.001,0.01,500);
        testRidge(trainDate, testDate,0.01,0.001,1000);

        System.out.println("--------------------------------------------------------------------------");

        testLasso(trainDate, testDate,0.01,0.1,100);//最优
        testLasso(trainDate, testDate,0.01,0.01,200);
        testLasso(trainDate, testDate,0.01,0.1,200);
        testLasso(trainDate, testDate,0.01,0.01,500);
        testLasso(trainDate, testDate,0.01,0.001,1000);
        // TODO: 2025/7/4 8.模型存储
        BatchOperator extracted = extracted(trainDate, testDate, 0.1, 100);
        CsvSinkBatchOp csvSink = new CsvSinkBatchOp()
                .setOverwriteSink(true)//覆盖
                .setFilePath("D:\\WorkSpace\\2301B\\lx_yk_month06\\out\\linear_out.txt");

        extracted.link(csvSink);

        BatchOperator.execute();

    }

    /**
     * 学习率和最大迭代步数的关系
     * @param trainDate
     * @param testDate
     * @param lrt
     * @param mt
     * @throws Exception
     */

    private static BatchOperator extracted(BatchOperator<?> trainDate, BatchOperator<?> testDate,double lrt,int mt) throws Exception {
        // TODO: 2025/7/4 4.算法模型训练
        //调优:就是调整超参数
        BatchOperator <?> lr = new LinearRegTrainBatchOp()
                .setLearningRate(lrt)
                .setMaxIter(mt)
                //特征列
                .setFeatureCols("x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13")
                //标签列
                .setLabelCol("y");
        //用训练集训练
        BatchOperator model = trainDate.link(lr);
        // TODO: 2025/7/4 5.算法模型预测
        BatchOperator <?> predictor = new LinearRegPredictBatchOp()
                //设置预测列
                .setPredictionCol("pred");
        //用测试集预测
        BatchOperator<?> o = predictor.linkFrom(model, testDate);
        o.print();
        // TODO: 2025/7/4 6.算法模型评估
        RegressionMetrics metrics = new EvalRegressionBatchOp()
                //预测列
                .setPredictionCol("pred")
                //真实列
                .setLabelCol("y")
                //预测数据集中包含真实列 和预测列
                .linkFrom(o)
                .collectMetrics();
        System.out.println("Total Samples Number:" + metrics.getCount());
        System.out.println("RMSE:" + metrics.getRmse());
        System.out.println("R2:" + metrics.getR2());

        return model;
    }




    private static BatchOperator testRidge(BatchOperator<?> trainDate,
                                           BatchOperator<?> testDate,
                                           double lrt,
                                           double lmd,
                                           int mt) throws Exception {
        // TODO: 2025/7/4 4.算法模型训练
        //调优:就是调整超参数
        BatchOperator <?> ridge = new RidgeRegTrainBatchOp()
                .setLambda(lmd)
                .setLearningRate(lrt)
                .setMaxIter(mt)
                //特征列
                .setFeatureCols("x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13")
                //标签列
                .setLabelCol("y");
        //用训练集训练
        BatchOperator model = trainDate.link(ridge);
        // TODO: 2025/7/4 5.算法模型预测
        BatchOperator <?> predictor = new RidgeRegPredictBatchOp()
                //设置预测列
                .setPredictionCol("pred");
        //用测试集预测
        BatchOperator<?> o = predictor.linkFrom(model, testDate);
        o.print();
        // TODO: 2025/7/4 6.算法模型评估
        RegressionMetrics metrics = new EvalRegressionBatchOp()
                //预测列
                .setPredictionCol("pred")
                //真实列
                .setLabelCol("y")
                //预测数据集中包含真实列 和预测列
                .linkFrom(o)
                .collectMetrics();
        System.out.println("Total Samples Number:" + metrics.getCount());
        System.out.println("RMSE:" + metrics.getRmse());
        System.out.println("R2:" + metrics.getR2());

        return model;
    }




    private static BatchOperator testLasso(BatchOperator<?> trainDate,
                                           BatchOperator<?> testDate,
                                           double lrt,
                                           double lmd,
                                           int mt) throws Exception {
        // TODO: 2025/7/4 4.算法模型训练
        //调优:就是调整超参数
        BatchOperator <?> lasso = new LassoRegTrainBatchOp()
                .setLambda(lmd)
                .setLearningRate(lrt)
                .setMaxIter(mt)
                //特征列
                .setFeatureCols("x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13")
                //标签列
                .setLabelCol("y");
        //用训练集训练
        BatchOperator model = trainDate.link(lasso);
        // TODO: 2025/7/4 5.算法模型预测
        BatchOperator <?> predictor = new LassoRegPredictBatchOp()
                //设置预测列
                .setPredictionCol("pred");
        //用测试集预测
        BatchOperator<?> o = predictor.linkFrom(model, testDate);
        o.print();
        // TODO: 2025/7/4 6.算法模型评估
        RegressionMetrics metrics = new EvalRegressionBatchOp()
                //预测列
                .setPredictionCol("pred")
                //真实列
                .setLabelCol("y")
                //预测数据集中包含真实列 和预测列
                .linkFrom(o)
                .collectMetrics();
        System.out.println("Total Samples Number:" + metrics.getCount());
        System.out.println("RMSE:" + metrics.getRmse());
        System.out.println("R2:" + metrics.getR2());

        return model;
    }
}
